#include "AlarmManager.h"
#include "core/ChannelManager.h"
#include "core/Channel.h"
#include <QFile>
#include <QJsonDocument>
#include <QUuid>
#include <QDebug>

namespace ModbusPlexLink {

// AlarmRule 序列化
QJsonObject AlarmRule::toJson() const {
    QJsonObject json;
    json["id"] = id;
    json["name"] = name;
    json["enabled"] = enabled;
    json["channelName"] = channelName;
    json["tagName"] = tagName;
    json["type"] = static_cast<int>(type);
    json["priority"] = static_cast<int>(priority);
    json["highLimit"] = highLimit;
    json["lowLimit"] = lowLimit;
    json["highHighLimit"] = highHighLimit;
    json["lowLowLimit"] = lowLowLimit;
    json["deadband"] = deadband;
    json["delaySeconds"] = delaySeconds;
    json["message"] = message;
    return json;
}

AlarmRule AlarmRule::fromJson(const QJsonObject& json) {
    AlarmRule rule;
    rule.id = json["id"].toString();
    rule.name = json["name"].toString();
    rule.enabled = json["enabled"].toBool(true);
    rule.channelName = json["channelName"].toString();
    rule.tagName = json["tagName"].toString();
    rule.type = static_cast<AlarmType>(json["type"].toInt());
    rule.priority = static_cast<AlarmPriority>(json["priority"].toInt());
    rule.highLimit = json["highLimit"].toDouble(100.0);
    rule.lowLimit = json["lowLimit"].toDouble(0.0);
    rule.highHighLimit = json["highHighLimit"].toDouble(120.0);
    rule.lowLowLimit = json["lowLowLimit"].toDouble(-10.0);
    rule.deadband = json["deadband"].toDouble(1.0);
    rule.delaySeconds = json["delaySeconds"].toInt(0);
    rule.message = json["message"].toString();
    return rule;
}

// AlarmEvent 序列化
QJsonObject AlarmEvent::toJson() const {
    QJsonObject json;
    json["id"] = id;
    json["ruleId"] = ruleId;
    json["ruleName"] = ruleName;
    json["type"] = static_cast<int>(type);
    json["priority"] = static_cast<int>(priority);
    json["state"] = static_cast<int>(state);
    json["channelName"] = channelName;
    json["tagName"] = tagName;
    json["value"] = value.toString();
    json["message"] = message;
    json["activeTime"] = activeTime.toString(Qt::ISODate);
    json["acknowledgedTime"] = acknowledgedTime.toString(Qt::ISODate);
    json["clearedTime"] = clearedTime.toString(Qt::ISODate);
    json["acknowledgedBy"] = acknowledgedBy;
    return json;
}

AlarmEvent AlarmEvent::fromJson(const QJsonObject& json) {
    AlarmEvent event;
    event.id = json["id"].toString();
    event.ruleId = json["ruleId"].toString();
    event.ruleName = json["ruleName"].toString();
    event.type = static_cast<AlarmType>(json["type"].toInt());
    event.priority = static_cast<AlarmPriority>(json["priority"].toInt());
    event.state = static_cast<AlarmState>(json["state"].toInt());
    event.channelName = json["channelName"].toString();
    event.tagName = json["tagName"].toString();
    event.value = json["value"];
    event.message = json["message"].toString();
    event.activeTime = QDateTime::fromString(json["activeTime"].toString(), Qt::ISODate);
    event.acknowledgedTime = QDateTime::fromString(json["acknowledgedTime"].toString(), Qt::ISODate);
    event.clearedTime = QDateTime::fromString(json["clearedTime"].toString(), Qt::ISODate);
    event.acknowledgedBy = json["acknowledgedBy"].toString();
    return event;
}

// AlarmManager 实现
AlarmManager::AlarmManager(ChannelManager* channelManager, QObject *parent)
    : QObject(parent)
    , m_channelManager(channelManager)
    , m_maxHistorySize(1000)
{
    if (!m_channelManager) {
        qWarning() << "AlarmManager: ChannelManager is null!";
        return;
    }

    // 连接现有通道的信号
    for (const QString& channelName : m_channelManager->getChannelNames()) {
        Channel* channel = m_channelManager->getChannel(channelName);
        if (channel) {
            connectChannelSignals(channel);
        }
    }

    // 监听新通道创建
    connect(m_channelManager, &ChannelManager::channelCreated, this, [this](const QString& name) {
        Channel* channel = m_channelManager->getChannel(name);
        if (channel) {
            connectChannelSignals(channel);
        }
    });
}

AlarmManager::~AlarmManager() {
}

void AlarmManager::connectChannelSignals(Channel* channel) {
    if (!channel) return;

    // 监听数据更新
    if (channel->getDataModel()) {
        connect(channel->getDataModel(), &UniversalDataModel::dataUpdated,
                this, &AlarmManager::onDataUpdated, Qt::UniqueConnection);
    }

    // 监听采集器连接状态
    connect(channel, &Channel::collectorStateChanged,
            this, &AlarmManager::onCollectorConnectionChanged, Qt::UniqueConnection);
}

QString AlarmManager::addRule(const AlarmRule& rule) {
    QMutexLocker locker(&m_rulesMutex);

    AlarmRule newRule = rule;
    if (newRule.id.isEmpty()) {
        newRule.id = QUuid::createUuid().toString(QUuid::WithoutBraces);
    }

    m_rules.append(newRule);

    emit ruleAdded(newRule.id);
    qInfo() << "[AlarmManager] 添加报警规则:" << newRule.name << "(" << newRule.id << ")";

    return newRule.id;
}

bool AlarmManager::updateRule(const QString& ruleId, const AlarmRule& rule) {
    QMutexLocker locker(&m_rulesMutex);

    for (int i = 0; i < m_rules.size(); ++i) {
        if (m_rules[i].id == ruleId) {
            m_rules[i] = rule;
            m_rules[i].id = ruleId;  // 保持ID不变
            emit ruleUpdated(ruleId);
            qInfo() << "[AlarmManager] 更新报警规则:" << rule.name << "(" << ruleId << ")";
            return true;
        }
    }

    qWarning() << "[AlarmManager] 未找到规则:" << ruleId;
    return false;
}

bool AlarmManager::removeRule(const QString& ruleId) {
    QMutexLocker locker(&m_rulesMutex);

    for (int i = 0; i < m_rules.size(); ++i) {
        if (m_rules[i].id == ruleId) {
            QString name = m_rules[i].name;
            m_rules.removeAt(i);

            // 同时清除该规则的活动报警
            m_activeAlarmsMap.remove(ruleId);
            m_delayCache.remove(ruleId);

            emit ruleRemoved(ruleId);
            qInfo() << "[AlarmManager] 删除报警规则:" << name << "(" << ruleId << ")";
            return true;
        }
    }

    qWarning() << "[AlarmManager] 未找到规则:" << ruleId;
    return false;
}

AlarmRule AlarmManager::getRule(const QString& ruleId) const {
    QMutexLocker locker(&m_rulesMutex);

    for (const AlarmRule& rule : m_rules) {
        if (rule.id == ruleId) {
            return rule;
        }
    }

    return AlarmRule();  // 返回空规则
}

QList<AlarmRule> AlarmManager::getAllRules() const {
    QMutexLocker locker(&m_rulesMutex);
    return m_rules;
}

void AlarmManager::clearAllRules() {
    QMutexLocker locker(&m_rulesMutex);
    m_rules.clear();
    m_activeAlarmsMap.clear();
    m_delayCache.clear();
    qInfo() << "[AlarmManager] 清除所有报警规则";
}

bool AlarmManager::enableRule(const QString& ruleId, bool enable) {
    QMutexLocker locker(&m_rulesMutex);

    for (int i = 0; i < m_rules.size(); ++i) {
        if (m_rules[i].id == ruleId) {
            m_rules[i].enabled = enable;
            qInfo() << "[AlarmManager] 规则" << m_rules[i].name
                    << (enable ? "已启用" : "已禁用");
            return true;
        }
    }

    return false;
}

QList<AlarmEvent> AlarmManager::getActiveAlarms() const {
    QMutexLocker locker(&m_alarmsMutex);
    return m_activeAlarms;
}

QList<AlarmEvent> AlarmManager::getAlarmHistory(const QDateTime& start, const QDateTime& end) const {
    QMutexLocker locker(&m_alarmsMutex);

    QList<AlarmEvent> filtered;
    for (const AlarmEvent& event : m_alarmHistory) {
        if (event.activeTime >= start && event.activeTime <= end) {
            filtered.append(event);
        }
    }

    return filtered;
}

AlarmEvent AlarmManager::getAlarmEvent(const QString& eventId) const {
    QMutexLocker locker(&m_alarmsMutex);

    // 先在活动报警中查找
    for (const AlarmEvent& event : m_activeAlarms) {
        if (event.id == eventId) {
            return event;
        }
    }

    // 再在历史中查找
    for (const AlarmEvent& event : m_alarmHistory) {
        if (event.id == eventId) {
            return event;
        }
    }

    return AlarmEvent();  // 返回空事件
}

bool AlarmManager::acknowledgeAlarm(const QString& eventId, const QString& acknowledgedBy) {
    bool found = false;
    QString ackBy;

    // 在锁内修改状态
    {
        QMutexLocker locker(&m_alarmsMutex);

        for (int i = 0; i < m_activeAlarms.size(); ++i) {
            if (m_activeAlarms[i].id == eventId) {
                m_activeAlarms[i].state = AlarmState::Acknowledged;
                m_activeAlarms[i].acknowledgedTime = QDateTime::currentDateTime();
                m_activeAlarms[i].acknowledgedBy = acknowledgedBy.isEmpty() ? tr("用户") : acknowledgedBy;
                ackBy = m_activeAlarms[i].acknowledgedBy;
                found = true;
                break;
            }
        }
    }

    // 在锁外发射信号
    if (found) {
        emit alarmAcknowledged(eventId);
        qInfo() << "[AlarmManager] 报警已确认:" << eventId << "by" << ackBy;
    }

    return found;
}

bool AlarmManager::clearAlarm(const QString& eventId) {
    bool found = false;

    // 在锁内执行清除操作
    {
        QMutexLocker locker(&m_alarmsMutex);

        for (int i = 0; i < m_activeAlarms.size(); ++i) {
            if (m_activeAlarms[i].id == eventId) {
                m_activeAlarms[i].state = AlarmState::Cleared;
                m_activeAlarms[i].clearedTime = QDateTime::currentDateTime();

                // 移到历史
                m_alarmHistory.prepend(m_activeAlarms[i]);
                if (m_alarmHistory.size() > m_maxHistorySize) {
                    m_alarmHistory.removeLast();
                }

                m_activeAlarms.removeAt(i);
                found = true;
                break;
            }
        }
    }

    // 在锁外发射信号
    if (found) {
        emit alarmCleared(eventId);
        qInfo() << "[AlarmManager] 报警已清除:" << eventId;
    }

    return found;
}

int AlarmManager::getActiveAlarmCount() const {
    QMutexLocker locker(&m_alarmsMutex);
    return m_activeAlarms.size();
}

int AlarmManager::getAlarmCount(AlarmPriority priority) const {
    QMutexLocker locker(&m_alarmsMutex);

    int count = 0;
    for (const AlarmEvent& event : m_activeAlarms) {
        if (event.priority == priority) {
            count++;
        }
    }
    return count;
}

int AlarmManager::getTotalAlarmCount() const {
    QMutexLocker locker(&m_alarmsMutex);
    return m_activeAlarms.size() + m_alarmHistory.size();
}

void AlarmManager::onDataUpdated(const QString& tagName, const DataPoint& point) {
    // 获取通道名称
    UniversalDataModel* udm = qobject_cast<UniversalDataModel*>(sender());
    if (!udm || !m_channelManager) return;

    QString channelName;
    for (const QString& name : m_channelManager->getChannelNames()) {
        Channel* channel = m_channelManager->getChannel(name);
        if (channel && channel->getDataModel() == udm) {
            channelName = name;
            break;
        }
    }

    if (channelName.isEmpty()) return;

    // 检查报警条件
    checkAlarmConditions(channelName, tagName, point);
}

void AlarmManager::onCollectorConnectionChanged(const QString& collectorName, bool connected) {
    // 处理连接丢失报警
    Channel* channel = qobject_cast<Channel*>(sender());
    if (!channel) return;

    QString channelName = channel->getName();

    QMutexLocker locker(&m_rulesMutex);
    for (const AlarmRule& rule : m_rules) {
        if (!rule.enabled) continue;
        if (rule.channelName != channelName) continue;
        if (rule.type != AlarmType::ConnectionLost) continue;

        if (!connected) {
            // 触发连接丢失报警
            triggerAlarm(rule, channelName, "Connection", QVariant("Lost"));
        } else {
            // 自动清除连接恢复
            autoClearAlarm(rule.id);
        }
    }
}

void AlarmManager::checkAlarmConditions(const QString& channelName,
                                         const QString& tagName,
                                         const DataPoint& point) {
    QMutexLocker locker(&m_rulesMutex);

    for (const AlarmRule& rule : m_rules) {
        if (!rule.enabled) continue;
        if (rule.channelName != channelName && rule.channelName != "*") continue;
        if (rule.tagName != tagName) continue;

        bool shouldTrigger = false;
        double value = point.value.toDouble();

        switch (rule.type) {
            case AlarmType::HighHighLimit:
                if (value > rule.highHighLimit) shouldTrigger = true;
                break;

            case AlarmType::HighLimit:
                if (value > rule.highLimit) shouldTrigger = true;
                break;

            case AlarmType::LowLimit:
                if (value < rule.lowLimit) shouldTrigger = true;
                break;

            case AlarmType::LowLowLimit:
                if (value < rule.lowLowLimit) shouldTrigger = true;
                break;

            case AlarmType::DataQuality:
                if (point.quality != DataQuality::Good) shouldTrigger = true;
                break;

            case AlarmType::ValueChange:
                // 值变化检测（需要存储上次值）
                // TODO: 实现值变化检测
                break;

            default:
                break;
        }

        if (shouldTrigger) {
            // 处理延时
            if (rule.delaySeconds > 0) {
                if (!m_delayCache.contains(rule.id)) {
                    // 第一次触发，记录时间
                    DelayEntry entry;
                    entry.firstTriggerTime = QDateTime::currentDateTime();
                    entry.value = point.value;
                    m_delayCache[rule.id] = entry;
                } else {
                    // 检查延时是否满足
                    DelayEntry& entry = m_delayCache[rule.id];
                    qint64 elapsed = entry.firstTriggerTime.secsTo(QDateTime::currentDateTime());
                    if (elapsed >= rule.delaySeconds) {
                        // 延时满足，触发报警
                        triggerAlarm(rule, channelName, tagName, point.value);
                        m_delayCache.remove(rule.id);  // 清除延时缓存
                    }
                }
            } else {
                // 无延时，立即触发
                triggerAlarm(rule, channelName, tagName, point.value);
            }
        } else {
            // 条件不满足，清除延时缓存
            m_delayCache.remove(rule.id);

            // 如果有活动报警，考虑自动清除（带死区）
            if (m_activeAlarmsMap.contains(rule.id)) {
                bool shouldClear = false;

                switch (rule.type) {
                    case AlarmType::HighLimit:
                        if (value < (rule.highLimit - rule.deadband)) shouldClear = true;
                        break;
                    case AlarmType::LowLimit:
                        if (value > (rule.lowLimit + rule.deadband)) shouldClear = true;
                        break;
                    case AlarmType::HighHighLimit:
                        if (value < (rule.highHighLimit - rule.deadband)) shouldClear = true;
                        break;
                    case AlarmType::LowLowLimit:
                        if (value > (rule.lowLowLimit + rule.deadband)) shouldClear = true;
                        break;
                    default:
                        break;
                }

                if (shouldClear) {
                    autoClearAlarm(rule.id);
                }
            }
        }
    }
}

void AlarmManager::triggerAlarm(const AlarmRule& rule,
                                 const QString& channelName,
                                 const QString& tagName,
                                 const QVariant& value) {
    // 检查是否已存在活动报警（避免重复触发）
    if (m_activeAlarmsMap.contains(rule.id)) {
        return;  // 已有活动报警，不重复触发
    }

    AlarmEvent event;
    event.id = QUuid::createUuid().toString(QUuid::WithoutBraces);
    event.ruleId = rule.id;
    event.ruleName = rule.name;
    event.type = rule.type;
    event.priority = rule.priority;
    event.state = AlarmState::Active;
    event.channelName = channelName;
    event.tagName = tagName;
    event.value = value;
    event.message = generateAlarmMessage(rule, value);
    event.activeTime = QDateTime::currentDateTime();

    // 在锁内添加到列表
    {
        QMutexLocker locker(&m_alarmsMutex);
        m_activeAlarms.append(event);
        m_activeAlarmsMap[rule.id] = event;
    }

    // 在锁外发射信号，避免死锁
    emit alarmTriggered(event);

    qWarning() << "[AlarmManager] *** 报警触发 ***"
               << "规则:" << rule.name
               << "| 标签:" << tagName
               << "| 值:" << value.toString()
               << "| 消息:" << event.message;
}

void AlarmManager::autoClearAlarm(const QString& ruleId) {
    if (!m_activeAlarmsMap.contains(ruleId)) return;

    QString eventId;

    // 在锁内执行清除操作
    {
        QMutexLocker locker(&m_alarmsMutex);

        AlarmEvent& event = m_activeAlarmsMap[ruleId];
        eventId = event.id;

        // 从活动报警中移除
        for (int i = 0; i < m_activeAlarms.size(); ++i) {
            if (m_activeAlarms[i].id == eventId) {
                m_activeAlarms[i].state = AlarmState::Cleared;
                m_activeAlarms[i].clearedTime = QDateTime::currentDateTime();

                // 移到历史
                m_alarmHistory.prepend(m_activeAlarms[i]);
                if (m_alarmHistory.size() > m_maxHistorySize) {
                    m_alarmHistory.removeLast();
                }

                m_activeAlarms.removeAt(i);
                break;
            }
        }

        m_activeAlarmsMap.remove(ruleId);
    }

    // 在锁外发射信号
    emit alarmCleared(eventId);
    qInfo() << "[AlarmManager] 报警自动清除:" << eventId;
}

QString AlarmManager::generateAlarmMessage(const AlarmRule& rule, const QVariant& value) const {
    QString msg = rule.message;

    if (msg.isEmpty()) {
        // 默认消息
        switch (rule.type) {
            case AlarmType::HighHighLimit:
                msg = tr("%1 超过高高限 (%2 > %3)").arg(rule.tagName).arg(value.toString()).arg(rule.highHighLimit);
                break;
            case AlarmType::HighLimit:
                msg = tr("%1 超过高限 (%2 > %3)").arg(rule.tagName).arg(value.toString()).arg(rule.highLimit);
                break;
            case AlarmType::LowLimit:
                msg = tr("%1 低于低限 (%2 < %3)").arg(rule.tagName).arg(value.toString()).arg(rule.lowLimit);
                break;
            case AlarmType::LowLowLimit:
                msg = tr("%1 低于低低限 (%2 < %3)").arg(rule.tagName).arg(value.toString()).arg(rule.lowLowLimit);
                break;
            case AlarmType::DataQuality:
                msg = tr("%1 数据质量异常").arg(rule.tagName);
                break;
            case AlarmType::ConnectionLost:
                msg = tr("%1 连接丢失").arg(rule.channelName);
                break;
            default:
                msg = tr("%1 触发报警").arg(rule.tagName);
                break;
        }
    } else {
        // 替换占位符
        msg.replace("{tagName}", rule.tagName);
        msg.replace("{value}", value.toString());
        msg.replace("{channelName}", rule.channelName);
    }

    return msg;
}

bool AlarmManager::loadConfig(const QString& filename) {
    QFile file(filename);
    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "[AlarmManager] 无法打开配置文件:" << filename;
        return false;
    }

    QByteArray data = file.readAll();
    file.close();

    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (doc.isNull() || !doc.isObject()) {
        qWarning() << "[AlarmManager] 配置文件格式错误";
        return false;
    }

    fromJson(doc.object());
    qInfo() << "[AlarmManager] 配置加载成功:" << filename;
    return true;
}

bool AlarmManager::saveConfig(const QString& filename) const {
    QFile file(filename);
    if (!file.open(QIODevice::WriteOnly)) {
        qWarning() << "[AlarmManager] 无法创建配置文件:" << filename;
        return false;
    }

    QJsonDocument doc(toJson());
    file.write(doc.toJson(QJsonDocument::Indented));
    file.close();

    qInfo() << "[AlarmManager] 配置保存成功:" << filename;
    return true;
}

QJsonObject AlarmManager::toJson() const {
    QMutexLocker locker(&m_rulesMutex);

    QJsonObject json;
    json["version"] = "1.0";
    json["maxHistorySize"] = m_maxHistorySize;

    QJsonArray rulesArray;
    for (const AlarmRule& rule : m_rules) {
        rulesArray.append(rule.toJson());
    }
    json["rules"] = rulesArray;

    return json;
}

void AlarmManager::fromJson(const QJsonObject& json) {
    QMutexLocker locker(&m_rulesMutex);

    m_rules.clear();
    m_maxHistorySize = json["maxHistorySize"].toInt(1000);

    QJsonArray rulesArray = json["rules"].toArray();
    for (const QJsonValue& val : rulesArray) {
        if (val.isObject()) {
            AlarmRule rule = AlarmRule::fromJson(val.toObject());
            m_rules.append(rule);
        }
    }

    qInfo() << "[AlarmManager] 加载" << m_rules.size() << "条报警规则";
}

} // namespace ModbusPlexLink
